package net

/**
  该插件不支持注册多个实例, 创建后不支持销毁
*/
import (
	"dgo/MyProj/PrjHttpUtils"
	"dgo/goutils/utils"
	"fmt"
	"gitee.com/ymofen/supervalue"
	"net/http"
	"os"
	"strings"
	"sync/atomic"
)

var (
	cmd_httpfilesvr_upload_registed_flag uint32 = 0
	resMap                               utils.GSyncMapGroup
)

type uploadHttpReq struct {
	w http.ResponseWriter
	r http.Request
}

type uploadFileConf struct {
	max_size       int64
	root           string
	def_existsflag int // 0:重命名, 1:覆盖
	plugin         interface{}
	aftercallback  func()
}

func findResConf(resid string) *uploadFileConf {
	v := resMap.Get(resid, nil)
	if v == nil {
		return nil
	}
	return v.(*uploadFileConf)
}

func checkGetResConf(resid string) *uploadFileConf {
	v := resMap.LoadOrStoreFunc(resid, func() interface{} {
		rval := &uploadFileConf{def_existsflag: 1, max_size: 1024 * 1024 * 10}
		return rval
	}, nil).(*uploadFileConf)
	return v
}

type ProjCmdHttpFileUpload struct {
	plugId string
	resid  string
}

func (this *ProjCmdHttpFileUpload) SetPlugID(val string) {
	this.plugId = val
}

func CheckRegisterUploadHandler() {
	if atomic.CompareAndSwapUint32(&cmd_httpfilesvr_upload_registed_flag, 0, 1) {
		http.HandleFunc("/sys/file/upload", UploadFile)
	}
}

/*
*
url 不注册反注册, 一定注册后不可以修改

	{
	   "id":"kpl",   // 资源ID
	   "root":"G:\\kpl\\"
	}
*/
func (this *ProjCmdHttpFileUpload) ReloadConf(conf *wrapper.SuperValue) error {
	CheckRegisterUploadHandler()
	conf.CheckStrFunc("id", func(strv string) {
		if this.resid != strv {
			confRec := findResConf(this.resid)
			if confRec != nil && confRec.plugin == this {
				resMap.Remove(this.resid)
			}
		}
		this.resid = strv
	})
	if len(this.resid) == 0 {
		return fmt.Errorf("请指定ID")
	}
	confRec := checkGetResConf(this.resid)
	if confRec.plugin == nil {
		confRec.plugin = this
	} else if confRec.plugin != this {
		return fmt.Errorf("资源ID:%s已经被其他插件注册", this.resid)
	}
	conf.CheckStrFunc("root", func(strv string) {
		confRec.root = strv
	})
	return nil
}

func (this *ProjCmdHttpFileUpload) OnObjectNotify(sender interface{}, notifytype int, data interface{}) (rval interface{}, err error) {
	if notifytype == utils.NOTIFY_TYPE_SETCONF {
		if conf, ok := data.(*wrapper.SuperValue); ok {
			err = this.ReloadConf(conf)
		} else {
			err = fmt.Errorf("非法的JSON配置")
		}
	} else if notifytype == utils.NOTIFY_TYPE_RELEASE {

	}
	return
}

func CreateProjCmdHttpFileUploadFunc(args ...interface{}) (rval interface{}, err error) {
	obj := &ProjCmdHttpFileUpload{}
	if len(args) > 0 {
		if str, ok := args[0].(string); ok {
			obj.plugId = str
		}
	}
	rval = obj
	return
}

/*
*

	url: upload?id=kpl&existsflag=0

	multiform:
	  filename:["xxx", "xx1"]
	  upfile: [FILE, FILE]
*/
func UploadFile(w http.ResponseWriter, r *http.Request) {
	resid := r.URL.Query().Get("id")
	if len(resid) == 0 {
		http.Error(w, "503 id is empty!!!", 503)
		return
	}
	obj := resMap.Get(resid, nil)
	if obj == nil {
		http.Error(w, "404 not found!", 404)
		return
	}
	resRec := obj.(*uploadFileConf)

	err := r.ParseMultipartForm(resRec.max_size)
	if err != nil {
		http.Error(w, fmt.Sprintf("解析MultiPartForm出现异常:%s", err.Error()), 503)
		return
	}

	strFileNames := r.MultipartForm.Value["filename"]
	strCopyFile := ""
	strs := r.MultipartForm.Value["copyfile"]
	if len(strs) > 0 {
		strCopyFile = strs[0]
	}

	files := r.MultipartForm.File["upfile"]
	if len(files) == 0 {
		files = r.MultipartForm.File["file"]
		if len(files) == 0 {
			http.Error(w, fmt.Sprintf("没有指定上传文件(%s)参数", "upfile"), 503)
			return
		}
	}

	tmpFile, err1 := files[0].Open()
	if err1 != nil {
		http.Error(w, fmt.Sprintf("打开文件出现异常:%s", err.Error()), 503)
		return
	}
	strFileID := ""
	strFileID = r.URL.Query().Get("filename")
	if len(strFileID) == 0 {
		if len(strFileNames) == 0 {
			strFileID = files[0].Filename
		} else {
			if len(strFileNames[0]) == 0 {
				strFileID = fmt.Sprintf("%s.tmp", utils.RandHexString(24))
			} else {
				strFileID = strFileNames[0]
			}
		}
	}
	strFileID = ReplacePlaceholderForFileName(strFileID)
	strFileName := resRec.root + strFileID
	utils.ForceCreateFilePath(strFileName)

	if utils.FileIsExists(strFileName) {
		existsflagstr := r.URL.Query().Get("existsflag")
		existsflag := resRec.def_existsflag

		if len(existsflagstr) > 0 {
			existsflag = utils.StrToIntDef(existsflagstr, 0)
		}

		if existsflag == 0 { // 重命名
			strFileName = utils.NewFileNameIfExistsThenIncSN(strFileName)
			strFileID = strings.TrimPrefix(strFileName, resRec.root)
		}
	}

	_, err = utils.NewFileFromReader(strFileName, tmpFile)
	if err != nil {
		http.Error(w, fmt.Sprintf("存储文件异常:%s", err.Error()), 503)
		return
	}

	if len(strCopyFile) > 0 {
		strCopyFile = ReplacePlaceholderForFileName(strCopyFile)
		strCopyFile = resRec.root + strCopyFile
		utils.ForceCreateFilePath(strCopyFile)
		if utils.FileIsExists(strCopyFile) {
			os.Remove(strCopyFile)
		}
		utils.CopyFile(strFileName, strCopyFile)
	}

	if resRec.aftercallback != nil {
		//resRec.aftercallback(strFileName, w, r)
		//w.WriteHeader(200)
	}

	PrjHttpUtils.ResponseJSONValues(w, "filename", strFileID)
}
